package visitor

import "fmt"

//访问者模式处理
// Go 的特点是快 小 简单 编译 运行 部署 开发 都是service mesh
// faas
// baas
// interface
func Producer(out chan int) {
	for i := 0; i < 100; i++ {
		out <- i
	}
	close(out)
}
func Coustomer(out chan int) chan int {
	res := make(chan int)
	go func() {
		var sum = 0
		for v := range out {
			sum += v
		}
		res <- sum
	}()
	return res
}

// go proucer
// r:=Coumtser
// <-r
// 堵塞知道 R->go runc 去->chanle->res->rest
// ret->gofun->go->un->init
// iryt
type Customer interface {
	Accept(Visitor)
}

//接收一个访问者
//访问者去访问对应的信息
// comnysr-acctevies
// viysoe-viste
// comue accteor
// orviecor

type Visitor interface {
	Visit(Customer)
}
type EnterpriseCustomer struct {
	name string
}
type CustomerCol struct {
	customers []Customer
}

func (c *CustomerCol) Add(customer Customer) {
	c.customers = append(c.customers, customer)
}
func (c *CustomerCol) Accept(visitor Visitor) {
	for _, cu := range c.customers {
		cu.Accept(visitor)
	}
}
func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
	return &EnterpriseCustomer{
		name: name,
	}
}
func (c *EnterpriseCustomer) Accept(visitor Visitor) {
	visitor.Visit(c)
}

type IndividualCustomer struct {
	name string
}

func NewIndividualCustomer(name string) *IndividualCustomer {
	return &IndividualCustomer{name: name}
}

func (c *IndividualCustomer) Accept(visitor Visitor) {
	visitor.Visit(c)
}

type ServiceRequestVisitor struct{}

func (*ServiceRequestVisitor) Visit(customer Customer) {
	switch c := customer.(type) {
	case *EnterpriseCustomer:
		fmt.Printf("serving enterprise customer %s\n", c.name)
	case *IndividualCustomer:
		fmt.Printf("serving individual customer %s\n", c.name)
	}
}

type AnalysisVisitor struct{}

func (*AnalysisVisitor) Visit(customer Customer) {
	switch c := customer.(type) {
	case *EnterpriseCustomer:
		fmt.Printf("analysis enterprise customer %s\n", c.name)
	}
}

type DapatCouter struct {
	name string
	loc  string
}

func NewDapatCouter(name string, loc string) *DapatCouter {
	return &DapatCouter{name: name, loc: loc}
}

func (d *DapatCouter) Accept(visitor Visitor) {
	visitor.Visit(d)
}

type DVistor struct{}

func (*DVistor) Visit(customer Customer) {
	//这里可以进行打印处理
	switch c := customer.(type) {
	case *DapatCouter:
		fmt.Printf("datacutsre: name :%s loc :%s", c.name, c.loc)
	}
}

// 我们可以 Couster Accept(vistor)
// vistor.vistis(counter)
//type visyer
// ytior
// case
// mname
//
// I->accept(B)
// B->visist(I)
//Http-?this->template->accept(this)->deper
